package com.ruoyi.fun.controller;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.fun.domain.EcOrder;
import com.ruoyi.fun.service.IEcOrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 微信消息推送验证Controller
 * 
 * @author ruoyi
 * @date 2025-01-20
 */
@Anonymous
@RestController
@RequestMapping("/wechat/message")
public class WechatMessageController extends BaseController
{
    private static final Logger logger = LoggerFactory.getLogger(WechatMessageController.class);
    
    // 微信配置的Token
    private static final String WECHAT_TOKEN = "wwwiterativecat";
    
    // 微信配置的EncodingAESKey
    private static final String ENCODING_AES_KEY = "KSLMmeMci5V8tNl9HQQFmsdJgqph5pMSpYUFhXIBMAM";
    
    @Autowired
    private IEcOrderService ecOrderService;
    
    /**
     * 微信服务器验证接口
     * 微信服务器会发送GET请求到此接口进行验证
     * 
     * @param signature 微信加密签名
     * @param timestamp 时间戳
     * @param nonce 随机数
     * @param echostr 随机字符串
     * @return 验证成功返回echostr，验证失败返回null
     */
    @GetMapping("/verify")
    public String verifyWechatMessage(
            @RequestParam("signature") String signature,
            @RequestParam("timestamp") String timestamp,
            @RequestParam("nonce") String nonce,
            @RequestParam("echostr") String echostr) {
        
        logger.info("收到微信验证请求 - signature: {}, timestamp: {}, nonce: {}, echostr: {}", 
                   signature, timestamp, nonce, echostr);
        
        try {
            // 验证签名
            if (checkSignature(signature, timestamp, nonce)) {
                logger.info("微信签名验证成功，返回echostr: {}", echostr);
                return echostr;
            } else {
                logger.error("微信签名验证失败");
                return null;
            }
        } catch (Exception e) {
            logger.error("微信验证过程中发生异常", e);
            return null;
        }
    }
    
    /**
     * 微信小程序确认收货通知接口
     * 处理微信服务器推送的订单结算事件
     * 
     * @param requestBody 微信推送的JSON数据
     * @return 处理结果
     */
    @PostMapping("/verify")
    public String handleWechatCallback(@RequestBody String requestBody) {
        logger.info("收到微信小程序确认收货通知: {}", requestBody);
        
        try {
            // 解析JSON数据
            ObjectMapper objectMapper = new ObjectMapper();
            Map<String, Object> callbackData = objectMapper.readValue(requestBody, Map.class);
            
            // 获取事件类型（注意：微信文档中字段名为Event，大写E）
            String eventType = (String) callbackData.get("Event");
            logger.info("事件类型: {}", eventType);
            
            // 处理订单结算事件
            if ("trade_manage_order_settlement".equals(eventType)) {
                return handleOrderSettlement(callbackData);
            }
            
            logger.warn("未知的事件类型: {}", eventType);
            return "success";
            
        } catch (Exception e) {
            logger.error("处理微信回调数据时发生异常", e);
            return "fail";
        }
    }
    
    /**
     * 处理订单结算事件，更新订单状态为已收货
     * 
     * @param callbackData 回调数据
     * @return 处理结果
     */
    private String handleOrderSettlement(Map<String, Object> callbackData) {
        try {
            // 根据微信文档，merchant_trade_no等字段直接在根级别
            String merchantTradeNo = (String) callbackData.get("merchant_trade_no");
            if (merchantTradeNo == null || merchantTradeNo.trim().isEmpty()) {
                logger.error("回调数据中缺少merchant_trade_no");
                return "fail";
            }
            
            logger.info("开始处理订单结算，商户订单号: {}", merchantTradeNo);
            
            // 记录其他相关字段用于调试
            String transactionId = (String) callbackData.get("transaction_id");
            String merchantId = (String) callbackData.get("merchant_id");
            Number confirmReceiveTime = (Number) callbackData.get("confirm_receive_time");
            Number settlementTime = (Number) callbackData.get("settlement_time");
            
            logger.info("订单结算详情 - 微信订单号: {}, 商户号: {}, 确认收货时间: {}, 结算时间: {}", 
                       transactionId, merchantId, confirmReceiveTime, settlementTime);
            
            // 根据订单号查询订单
            EcOrder queryOrder = new EcOrder();
            queryOrder.setOrderNo(merchantTradeNo);
            List<EcOrder> orderList = ecOrderService.selectEcOrderList(queryOrder);
            
            if (orderList == null || orderList.isEmpty()) {
                logger.error("未找到订单，订单号: {}", merchantTradeNo);
                return "fail";
            }
            
            EcOrder order = orderList.get(0);
            logger.info("找到订单，当前状态: {}, 订单ID: {}", order.getOrderStatus(), order.getOrderId());
            
            String currentStatus = order.getOrderStatus();
            String newStatus = null;
            String statusDescription = null;
            
            // 根据当前状态决定新状态
            if ("2".equals(currentStatus)) {
                // 状态为'2'（已支付），更新为'3'（待收货）
                newStatus = "3";
                statusDescription = "待收货";
                order.setOrderStatus(newStatus);
                order.setDeliveryTime(DateUtils.getNowDate()); // 设置发货时间
                logger.info("订单状态从2（已支付）更新为3（待收货），设置发货时间: {}", DateUtils.getNowDate());
            } else if ("3".equals(currentStatus)) {
                // 状态为'3'（待收货），更新为'4'（已收货）
                newStatus = "4";
                statusDescription = "已收货";
                order.setOrderStatus(newStatus);
                order.setReceiveTime(DateUtils.getNowDate()); // 设置收货时间
                logger.info("订单状态从3（待收货）更新为4（已收货），设置收货时间: {}", DateUtils.getNowDate());
            } else {
                logger.warn("订单状态不符合更新条件，当前状态: {}, 订单号: {}。只支持状态2->3或3->4的转换", 
                           currentStatus, merchantTradeNo);
                return "success"; // 返回成功，避免微信重复推送
            }
            
            // 执行订单状态更新
            int updateResult = ecOrderService.updateEcOrder(order);
            if (updateResult > 0) {
                logger.info("订单状态更新成功，订单号: {}, 状态从{}更新为{}（{}）", 
                           merchantTradeNo, currentStatus, newStatus, statusDescription);
                return "success";
            } else {
                logger.error("订单状态更新失败，订单号: {}", merchantTradeNo);
                return "fail";
            }
            
        } catch (Exception e) {
            logger.error("处理订单结算事件时发生异常", e);
            return "fail";
        }
    }
    
    /**
     * 验证微信签名
     * 
     * @param signature 微信加密签名
     * @param timestamp 时间戳
     * @param nonce 随机数
     * @return 验证结果
     */
    private boolean checkSignature(String signature, String timestamp, String nonce) {
        try {
            // 1. 将token、timestamp、nonce三个参数进行字典序排序
            String[] array = {WECHAT_TOKEN, timestamp, nonce};
            Arrays.sort(array);
            
            // 2. 将三个参数字符串拼接成一个字符串
            StringBuilder sb = new StringBuilder();
            for (String str : array) {
                sb.append(str);
            }
            String sortedString = sb.toString();
            
            logger.info("排序后的字符串: {}", sortedString);
            
            // 3. 进行SHA1加密
            String sha1Result = sha1(sortedString);
            
            logger.info("SHA1计算结果: {}, 微信传入的signature: {}", sha1Result, signature);
            
            // 4. 与signature对比，相等则验证通过
            return sha1Result != null && sha1Result.equals(signature);
            
        } catch (Exception e) {
            logger.error("验证签名时发生异常", e);
            return false;
        }
    }
    
    /**
     * SHA1加密
     * 
     * @param str 待加密字符串
     * @return 加密结果
     */
    private String sha1(String str) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            byte[] digest = md.digest(str.getBytes());
            
            // 将字节数组转换为十六进制字符串
            StringBuilder sb = new StringBuilder();
            for (byte b : digest) {
                sb.append(String.format("%02x", b));
            }
            
            return sb.toString();
            
        } catch (NoSuchAlgorithmException e) {
            logger.error("SHA1加密失败", e);
            return null;
        }
    }
    
    /**
     * AES解密方法（兼容模式下可能需要）
     * 
     * @param encryptedData 加密数据
     * @param key AES密钥
     * @param iv 初始化向量
     * @return 解密后的数据
     */
    private String aesDecrypt(String encryptedData, String key, String iv) {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(key + "=");
            byte[] ivBytes = Base64.getDecoder().decode(iv + "=");
            byte[] dataBytes = Base64.getDecoder().decode(encryptedData);
            
            SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
            
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
            
            byte[] decryptedBytes = cipher.doFinal(dataBytes);
            return new String(decryptedBytes, "UTF-8");
            
        } catch (Exception e) {
            logger.error("AES解密失败", e);
            return null;
        }
    }
}